package core;

import static org.junit.Assert.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.junit.BeforeClass;
import org.junit.Test;

public class ImgTest {
	private static final String tests_path = "tests_images/";
	
	private static byte local_jpg[];
	private static byte local_bmp[];
	private static byte local_gif[];
	private static byte local_png[];
	
	private static byte local_compress_jpg[];
	private static byte local_compress_gif[];
	private static byte local_compress_bmp[];
	private static byte local_compress_png[];
	
	private static byte local_compress_scaledwidth_jpg[];
	private static byte local_compress_scaledheight_jpg[];
	
	private static String local_hash_image;
	
	/*
	 * Private tests functions.
	 */
	private static byte[] preparaTestImagen(String name)
	throws IOException {
		FileInputStream fdin;
		File fd;
		
		fd = new File(name);
		fdin = new FileInputStream(name);
		return Util.recoverDatafromInputStream(fdin, (int)fd.length());
	}
	
	private static String preparaHash(String urlstr)
	throws NoSuchAlgorithmException, IOException {
		MessageDigest md;
		
		md = MessageDigest.getInstance("SHA-1");
		md.update(urlstr.getBytes());
		return Util.byteArray2HexStr(md.digest());
	}
	
	// Tests functions.
	
	@BeforeClass  	
	public static void setUpClass() throws Exception {
		local_jpg = preparaTestImagen(tests_path + "RootedLabs.jpg");
		local_gif = preparaTestImagen(tests_path + "RootedLabs.gif");
		local_bmp = preparaTestImagen(tests_path + "RootedLabs.bmp");
		local_png = preparaTestImagen(tests_path + "RootedLabs.png");
		
		local_compress_jpg = preparaTestImagen(tests_path + "RootedLabsCompress.jpg");
		local_compress_gif = preparaTestImagen(tests_path + "RootedLabsCompressFromGif.jpg");
		local_compress_bmp = preparaTestImagen(tests_path + "RootedLabsCompressFromBmp.jpg");
		local_compress_png = preparaTestImagen(tests_path + "RootedLabsCompressFromPng.jpg");
		
		local_compress_scaledwidth_jpg = preparaTestImagen(tests_path + "RootedLabsCompressScaledWidth.jpg");
		local_compress_scaledheight_jpg = preparaTestImagen(tests_path + "RootedLabsCompressScaledHeight.jpg");
		
		local_hash_image = preparaHash("http://www.informatica64.com/dust/images/RootedLabs.jpg");
	}

	@Test
	public void testImg() {
		// Correct case.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.jpg");
			Img imagen = new Img(url);		
			assertEquals(imagen.getUrl(), url);
		}
		catch (Exception e) {
			fail("Exception thrown.");
		}
	}
	
	@Test
	public void testSetTypeFromFile() {
		URL url ;
		String name;
		Img imagen;
		
		// Correct case.
		try {
			name = "nombre_correcto.jpg.dust";
			url = new URL("http://noserver/nofile");
			imagen = new Img(url);
			imagen.setTypeFromFile(name);
			assertArrayEquals(imagen.getType().toCharArray(), "jpg".toCharArray());
		}
		catch (Exception e) {
			fail("Exception thrown.");
		}
		
		// Incorrect case, the name has no '.'.
		try {
			name = "nombre_incorrecto";
			url = new URL("http://noserver/nofile");
			imagen = new Img(url);
			if (imagen.setTypeFromFile(name))
				throw new Exception("");
		}
		catch (Exception e) {
			fail("Exception thrown.");
		}
		
		// Incorrect case, the name doesn't has two '.'.
		try {
			name = "nombre_incorrecto_sin_dos_puntos.jpg";
			url = new URL("http://noserver/nofile");
			imagen = new Img(url);
			if (imagen.setTypeFromFile(name))
				throw new Exception("");
		}
		catch (Exception e) {
			fail("Exception thrown.");
		}
	}

	@Test
	public void testGetImage() {
		// Correct case reading from a jpeg.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.jpg");
			Img imagen = new Img(url);			
			assertArrayEquals(imagen.getImage(), local_jpg);
		}
		catch (Exception e) {
			fail("Exception thrown in correct case.");
		}
		
		// Correct case reading from a gif.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.gif");
			Img imagen = new Img(url);			
			assertArrayEquals(imagen.getImage(), local_gif);
		}
		catch (Exception e) {
			fail("Exception thrown in correct case.");
		}
		
		// Correct case reading for a bmp.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.bmp");
			Img imagen = new Img(url);			
			assertArrayEquals(imagen.getImage(), local_bmp);
		}
		catch (Exception e) {
			fail("Exception thrown in correct case.");
		}
		
		// Correct case reading from a png.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.png");
			Img imagen = new Img(url);			
			assertArrayEquals(imagen.getImage(), local_png);
		}
		catch (Exception e) {
			fail("Exception thrown in correct case.");
		}
		
		// Incorrect case, image nonexistent.
		try {
			URL url = new URL("http://www.marca.com/superman8.jpg");
			Img imagen = new Img(url);	
			imagen.getImage();
			fail("An exception should be thrown.");
		}
		catch (Exception e) {}
		
		// Incorrect case, nonexistent domain.
		try {
			URL url = new URL("http://mierda/superman8.jpg");
			Img imagen = new Img(url);	
			imagen.getImage();
			fail("An exception should be thrown.");
		}
		catch (Exception e) {}
	}
	
	@Test
	public void testGetCompressImage() {
		// Correct case from jpeg.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.jpg");
			Img imagen = new Img(url);
			assertArrayEquals(imagen.getCompressImage(), local_compress_jpg);
		}
		catch (Exception e) {
			fail("Exception thrown in correct case.");
		}
		
		// Correct case from png.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.png");
			Img imagen = new Img(url);
			assertArrayEquals(imagen.getCompressImage(), local_compress_png);
		}
		catch (Exception e) {
			fail("Exception thrown in correct case.");
		}
		
		// Correct case from gif.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.gif");
			Img imagen = new Img(url);			
			assertArrayEquals(imagen.getCompressImage(), local_compress_gif);
		}
		catch (Exception e) {
			fail("Exception thrown in correct case.");
		}
		
		// Correct case from bmp.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.bmp");
			Img imagen = new Img(url);
			assertArrayEquals(imagen.getCompressImage(), local_compress_bmp);
		}
		catch (Exception e) {
			fail("Exception thrown in correct case.");
		}
		
		// Correct case scaling from jpg and asking for the width.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.jpg");
			Img imagen = new Img(url);
			assertArrayEquals(imagen.getCompressImage(100, -1), local_compress_scaledwidth_jpg);
		}
		catch (Exception e) {
			fail("Exception thrown in correct case.");
		}
		
		// Correct case scaling from gif and asking for the width.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.gif");
			Img imagen = new Img(url);
			assertArrayEquals(imagen.getCompressImage(100, -1), local_compress_scaledwidth_jpg);
		}
		catch (Exception e) {
			fail("Exception thrown in correct case.");
		}
		
		// Correct case scaling from bmp and asking for the width.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.bmp");
			Img imagen = new Img(url);
			assertArrayEquals(imagen.getCompressImage(100, -1), local_compress_scaledwidth_jpg);
		}
		catch (Exception e) {
			fail("Exception thrown in correct case.");
		}
		
		// Correct case scaling from jpg and asking for the height.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.jpg");
			Img imagen = new Img(url);
			assertArrayEquals(imagen.getCompressImage(-1, 25), local_compress_scaledheight_jpg);
		}
		catch (Exception e) {
			fail("Exception thrown in correct case.");
		}
		
		// Correct case scaling from gif and asking for the height.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.gif");
			Img imagen = new Img(url);
			assertArrayEquals(imagen.getCompressImage(-1, 25), local_compress_scaledheight_jpg);
		}
		catch (Exception e) {
			fail("Exception thrown in correct case.");
		}
		
		// Correct case scaling from bmp and asking for the height.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.bmp");
			Img imagen = new Img(url);
			assertArrayEquals(imagen.getCompressImage(-1, 25), local_compress_scaledheight_jpg);
		}
		catch (Exception e) {
			fail("Exception thrown in correct case.");
		}
		
		// Correct case, the image is not scaled.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.jpg");
			Img imagen = new Img(url);
			imagen.getCompressImage(258, -1);
		}
		catch (Exception e) {
			fail("Exception thrown.");
		}
	}
	
	@Test
	public void testGetType() {
		// Correct case with a bmp.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.bmp");
			Img imagen = new Img(url);
			imagen.getImage();
			assertArrayEquals(imagen.getType().toCharArray(), "bmp".toCharArray());
		}
		catch (Exception e) {
			fail("Exception thrown in correct case.");
		}
		
		// Correct case with a jpeg.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.jpg");
			Img imagen = new Img(url);
			imagen.getImage();
			assertArrayEquals(imagen.getType().toCharArray(), "jpeg".toCharArray());
		}
		catch (Exception e) {
			fail("Exception thrown in correct case.");
		}
	}
	
	@Test
	public void testGetHash() {
		// Correct case.
		try {
			URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.jpg");
			Img imagen = new Img(url);
			assertArrayEquals(imagen.getHash().toCharArray(), local_hash_image.toCharArray());
		}
		catch (Exception e) {
			fail("Exception thrown.");
		}
	}
	
	@Test
	public void testSave2File() throws MalformedURLException {
		String fname = "testsavingimage";
		File img_fd;
		URL url = new URL("http://www.informatica64.com/dust/images/RootedLabs.jpg");
		
		// Correct case.
		try {
			Img imagen = new Img(url);
			
			// Saving.
			imagen.getImage();
			imagen.save2File(fname);
			
			// Checking if saved.
			img_fd = new File(fname);
			if (!img_fd.exists())
				fail("Image not saved.");
			else
				img_fd.delete();
		}
		catch (Exception e) {
			e.printStackTrace();
			fail("Exception was thrown.");
		}
		
		// Wrong case, the image was not loaded.
		try {
			Img imagen = new Img(url);
			imagen.save2File(fname);
			fail ("Exception was not thrown.");
		}
		catch (Exception e) {}
		
		// Wrong case, the path to the file doesn't exists.
		try {
			Img imagen = new Img(url);
			imagen.save2File("non_existent_path/image");
			fail ("Exception was not thrown.");
		}
		catch (Exception e) {}
	}
}
